home *** CD-ROM | disk | FTP | other *** search
- Subject: v24i082: Qterm5.0 -- Query terminal for its type, Part01/02
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: 23817b14 f66cb394 106806de f16726fa
-
- Submitted-by: "Michael A. Cooper" <mcooper@usc.edu>
- Posting-number: Volume 24, Issue 82
- Archive-name: qterm5.0/part01
-
- Qterm is a program that queries terminals to find out what kind of
- terminal is responding. It is useful to automagically define your
- terminal type. It prints the name of the terminal (compatible,
- hopefully, with a termcap/terminfo name) such as "vt100" to standard
- output. See the manual for details.
-
- The major changes in these version of qterm is a re-write of command
- line parsing and the options qterm accepts. I've written a new,
- "generic" command line parsing package called "options" which is
- included as part of this distribution of qterm. (See the options.3
- man page for details on programming with the options package.) Qterm
- now has a totally new set of (hopefully) clear and concise options.
- The old command line options are still accepted if qterm is compiled
- with OPT_COMPAT defined (see Makefile). WARNING: Some of the old
- options conflict with the new options. i.e. If OPT_COMPAT is
- defined, "qterm -file foo" does not do what you think it will. This
- is parsed as "qterm -f ile foo".
-
- Qterm was written under 4.[23] BSD and will probably run without
- modification on other Berkeley Unix systems. This version has also
- been tested under UTS 2.1 which is a System V.3 derivative. It was
- compiled with "USG5" defined and setting $(LIBS) to "-lPW". (See
- Makefile for more info). It should work on other System V platforms.
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: README options.3 options.c options.h qterm.c
- # Wrapped by rsalz@litchi.bbn.com on Fri Mar 22 12:25:37 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 1 (of 2)."'
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(2200 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- X
- X Q T E R M - Q U E R Y T E R M I N A L
- X
- X Version 5.0
- X
- XQterm is a program that queries terminals to find out what kind of
- Xterminal is responding. It is useful to automagically define your
- Xterminal type. It prints the name of the terminal (compatible,
- Xhopefully, with a termcap/terminfo name) such as "vt100" to standard
- Xoutput. See the manual for details.
- X
- XThe major changes in these version of qterm is a re-write of command
- Xline parsing and the options qterm accepts. I've written a new,
- X"generic" command line parsing package called "options" which is
- Xincluded as part of this distribution of qterm. (See the options.3
- Xman page for details on programming with the options package.) Qterm
- Xnow has a totally new set of (hopefully) clear and concise options.
- XThe old command line options are still accepted if qterm is compiled
- Xwith OPT_COMPAT defined (see Makefile). WARNING: Some of the old
- Xoptions conflict with the new options. i.e. If OPT_COMPAT is
- Xdefined, "qterm -file foo" does not do what you think it will. This
- Xis parsed as "qterm -f ile foo".
- X
- XQterm was written under 4.[23] BSD and will probably run without
- Xmodification on other Berkeley Unix systems. This version has also
- Xbeen tested under UTS 2.1 which is a System V.3 derivative. It was
- Xcompiled with "USG5" defined and setting $(LIBS) to "-lPW". (See
- XMakefile for more info). It should work on other System V platforms.
- X
- XIt has been running at one point or another here at USC on:
- X
- X Sun-3, Sun-4, Sun386i's under SunOS 3.X, 4.0, 4.0.3, 4.1, 4.1.1
- X Alliant's under Concentrix 3.X, 4.X, 5.X
- X IBM RT's under ACIS 4.2 and 4.3
- X DEC VAX & DEC RISC under Ultrix 2.2, 3.1, 4.0, 4.1
- X 4.[23]BSD (VAX)
- X 4.3BSD [MORE/bsd] (HP)
- X Amdahl UTS (System V.3) 2.1
- X
- XIf you have Internet access, the latest and greatest version of qterm
- Xis available from "usc.edu" via anonymous ftp in the file
- X/pub/qterm.shar. I update this file whenever there are any changes,
- Xso it's bound to be newer than a copy from any other source.
- X
- X
- XMichael A. Cooper, University Computing Services, U of Southern California
- X INTERNET: mcooper@usc.edu PHONE: 213-740-2957
- X UUCP: ...!uunet!usc!mcooper BITNET: mcooper@gamera
- END_OF_FILE
- if test 2200 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'options.3' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'options.3'\"
- else
- echo shar: Extracting \"'options.3'\" \(7383 characters\)
- sed "s/^X//" >'options.3' <<'END_OF_FILE'
- X.\"
- X.\" Copyright (c) 1990 Michael A. Cooper.
- X.\" This software may be freely distributed provided it is not sold for
- X.\" profit and the author is credited appropriately.
- X.\"
- X.\" $Header: /src/common/usc/lib/libgen/RCS/options.3,v 1.4 1991/02/22 02:30:06 mcooper Exp $
- X.\"
- X.TH PARSEOPTIONS 3 "30 October 1990"
- X.ds ]W USC-UCS
- X.SH NAME
- XParseOptions, UsageOptions, HelpOptions, Num_Opts \- Parse command line options
- X.SH SYNOPSIS
- X.LP
- X.nf
- X.ft B
- X#include "/usr/usc/include/options.h"
- X.ft
- X.fi
- X.LP
- X.nf
- X.ft B
- Xint ParseOptions(options, num_options, argc, argv)
- XOptionDescRec *options;
- Xint num_options;
- Xint argc;
- Xchar **argv;
- X.ft
- X.fi
- X.LP
- X.nf
- X.ft B
- Xvoid UsageOptions(options, num_options, badoption)
- XOptionDescRec *options;
- Xint num_options;
- Xchar *badoption;
- X.ft
- X.fi
- X.LP
- X.nf
- X.ft B
- Xvoid HelpOptions(options, num_options, message)
- XOptionDescRec *options;
- Xint num_options;
- Xchar **message;
- X.ft
- X.fi
- X.LP
- X.nf
- X.ft B
- Xint Num_Opts(options)
- XOptionDescRec *options;
- X.ft
- X.fi
- X.LP
- X.nf
- X.ft B
- Xextern char *OptionChars;
- Xextern char *ProgramName;
- X.ft
- X.fi
- X.SH DESCRIPTION
- X.LP
- X.BR ParseOptions(\|)
- Xparses a given set of options found in
- X.B argv.
- XThe
- X.B argc
- Xparameter is the count of the number of string pointers
- Xin
- X.B argv.
- XBoth
- X.B argc
- Xand
- X.B argv
- Xare typically passed directly from a
- X.B main(\|)
- Xfunction.
- XThe
- X.B argv
- Xparameter should contain an array of strings that
- Xneed to be parsed.
- X.B ParseOptions(\|)
- Xreturns the number of entries in
- X.B argv
- Xthat were successfully parsed or -1 upon error.
- X.LP
- XThe
- X.B options
- Xstructure should contain a valid description list of options.
- XThe type
- X.B OptionDescRec
- Xis defined as the following in the
- X.B "options.h"
- Xheader file:
- X.RS
- X.LP
- X.nf
- X.ft B
- Xtypedef struct {
- X char *option; /* Option string in argv */
- X int flags; /* Flag bits */
- X int (*cvtarg)(); /* Function to convert argument */
- X caddr_t valp; /* Variable to set */
- X caddr_t value; /* Default value to provide */
- X char *usage; /* Usage message */
- X char *desc; /* Description message */
- X} OptionDescRec, *OptionDescList;
- X.ft R
- X.fi
- X.RE
- X.LP
- XThe order of
- X.I options
- Xis important because
- Xthe first partial match found in
- X.I options
- Xis used.
- XThis allows abbreviations (except if the option is a
- X.I StickArg
- X[see below]).
- XFor instance, a user may specify only "\-n" for "\-number" provided
- Xthat "\-n" is unique to
- X.I options
- Xor that "\-number" is placed before any other "\-n*" options in
- X.I options.
- X.LP
- XThe
- X.I option
- Xmember of
- X.B OptionDescRec
- Xis the string name of the option.
- XThis is typically something like
- X.RS
- X.ft B
- X.nf
- X.sp
- X"\-c"
- X"+c"
- X"\-file"
- X.fi
- X.sp
- X.ft
- X.RE
- XThe first character of
- X.I option
- Xis special. It must be one of the characters know to be the
- Xstart of an option.
- XThe default list of starting option characters is "\-+".
- XThis indicates that an option can start with either a "\-" or
- Xa "+". This list of characters may be changed by setting
- Xthe variable
- X.B OptionChars
- Xto point to a string of custom starting option characters.
- X.LP
- XThe
- X.I flags
- Xmember is used to set bits to describe how an option
- Xis to be interpreted.
- XValid flags are defined in the
- X.I "options.h"
- Xheader file:
- X.RS
- X.IP NoArg
- XNo argument for this option.
- XUse the value in
- X.I OptionDescRec.value
- Xto set the value in the
- X.I valp
- Xmember of
- X.B OptionDescRec.
- X.IP IsArg
- XValue is the option string itself.
- X.IP SepArg
- XValue is in next argument in argv.
- X.IP StickyArg
- XValue is the characters immediately following
- Xthe option.
- X.IP SkipArg
- XIgnore this option and the next argument in argv.
- X.IP SkipLine
- XIgnore this option and the rest of argv.
- X.IP SkipNArgs
- XIgnore this option and the next
- X.I OptionDescRes.value
- Xarguments in argv.
- X.IP ArgHidden
- XDon't show this option in usage or help messages.
- X.RE
- X.LP
- XThe next member of
- X.B OptionDescRec
- Xis
- X.I cvtarg.
- XThis should be a pointer to a function that knows how to
- Xconvert the given argument into the correct type.
- XThe predefined functions are as follows:
- X.RS
- X.IP OptBool
- XConverts a boolean.
- X.IP OptInt
- XConverts an integer.
- X.IP OptShort
- XConverts a short.
- X.IP OptLong
- XConverts a long.
- X.IP OptStr
- XConverts a string.
- X.RE
- X.LP
- XThe
- X.I valp
- Xmember should be a pointer
- Xto the variable that needs to be set.
- X.I valp
- Xshould accept whatever type
- X.I cvtarg
- Xis expected to return.
- X.LP
- XThe
- X.I value
- Xmember should contain a default value to
- Xbe used if no value is given for an option or
- Xthis type of option does not require an argument
- X(according to the
- X.I flags
- Xbits).
- XIf
- X.I value
- Xis
- X.B NULL
- Xthen an argument for this option
- Xis optional.
- X.LP
- X.I usage
- Xis used to build usage and help messages.
- XIt should be a string containing a description of any arguments
- Xthat may be used for this option.
- XThe option string itself should not be a part of
- X.I usage.
- XThe
- X.B UsageOptions(\|)
- Xand
- X.B HelpOptions(\|)
- Xfunctions combine the
- X.I option
- Xfield with
- X.I usage
- Xand interpret the
- X.I flags
- Xbits to build a usage string.
- XIf this field is
- X.B NULL,
- Xthen just the
- X.I option
- Xfield itself is used for usage and help messages.
- X.LP
- XThe
- X.I desc
- Xmember is used to build a help message for this option.
- XThis should be a string containing a brief description on what this
- Xoption does.
- X.LP
- XThe
- X.B num_options
- Xparameter should be the number of
- X.B OptionDescRec's
- Xfound in
- X.B options.
- XThe function
- X.BR Num_Opts(\|)
- Xwill return the number of
- X.B OptionDescRec's.
- X.LP
- XThe
- X.B UsageOptions(\|)
- Xfunction
- Xprints a usage message.
- XIf
- X.I badoption
- Xis not
- X.B NULL,
- Xthen an initial message is displayed indicating that
- X.I badoption
- Xis not a valid option.
- X.LP
- XThe
- X.B HelpOptions(\|)
- Xfunction
- Xprints a nicely formatted message describing all options.
- XIf
- X.I message
- Xis not
- X.B NULL
- Xit is taken to be a message that is displayed in the output of
- Xa "\-help" option.
- X.SH EXAMPLE
- X.LP
- XHere is an example program:
- X.nf
- X.sp
- X.ft B
- X#include "options.h"
- X
- Xchar *filename = NULL;
- Xint number = \-1;
- Xint foo = \-1;
- Xint I = \-1;
- Xlong L = \-1;
- Xshort S = \-1;
- X
- XOptionDescRec opts[] = {
- X {"\-foo", NoArg, OptBool, (caddr_t) &foo, "0",
- X (char *)NULL, "Disable foo bar"},
- X {"+foo", NoArg, OptBool, (caddr_t) &foo, "1",
- X (char *)NULL, "Enable foo bar"},
- X {"\-I", StickyArg, OptInt, (caddr_t) &I, (caddr_t) NULL,
- X (char *)NULL, "Set value of I"},
- X {"\-L", StickyArg, OptLong, (caddr_t) &L, (caddr_t) NULL,
- X (char *)NULL, "Set value of L"},
- X {"\-S", SepArg, OptShort, (caddr_t) &S, (caddr_t) NULL,
- X (char *)NULL, "Set value of S"},
- X {"\-C", StickyArg, OptStr, (caddr_t) &filename, (caddr_t) NULL,
- X (char *)NULL, "Alternate file to use"},
- X {"\-number", SepArg, OptInt, (caddr_t) &number, "66",
- X "interval", NULL},
- X {"\-file", SepArg, OptStr, (caddr_t) &filename, (caddr_t) NULL,
- X "filename", "Specify alternate file to use"},
- X};
- X
- Xmain(argc, argv)
- X int argc;
- X char **argv;
- X{
- X int c;
- X
- X c = ParseOptions(opts, Num_Opts(opts), argc, argv);
- X printf("Count = %d of %d\n", c, argc);
- X}
- X.ft
- X.fi
- X.SH "RETURN VALUES"
- X.B ParseOptions(\|)
- Xreturns the number of arguments parsed or -1 upon error.
- X.SH NOTES
- X.LP
- XThe
- X.I \-help
- Xoption is automatically built into
- X.B ParseOptions(\|).
- X.LP
- XAll error messages are sent to
- X.B stderr.
- X.LP
- XAn option may be both
- X.I StickyArg
- Xand
- X.I SepArg.
- XIf both are set for one option, preference is given to
- X.I SepArg
- Xparsing.
- XAlso, no appreviations are allowed.
- X.SH AUTHOR
- XMichael A. Cooper,
- X.br
- XUniversity Computing Services,
- X.br
- XUniversity of Southern California.
- END_OF_FILE
- if test 7383 -ne `wc -c <'options.3'`; then
- echo shar: \"'options.3'\" unpacked with wrong size!
- fi
- # end of 'options.3'
- fi
- if test -f 'options.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'options.c'\"
- else
- echo shar: Extracting \"'options.c'\" \(10901 characters\)
- sed "s/^X//" >'options.c' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1990 Michael A. Cooper.
- X * This software may be freely distributed provided it is not sold for
- X * profit and the author is credited appropriately.
- X */
- X
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /am/sol/src/common/usc/lib/libgen/RCS/options.c,v 1.13 90/12/15 18:13:28 mcooper Exp $";
- X#endif
- X
- X/*
- X * $Log: options.c,v $
- X * Revision 1.13 90/12/15 18:13:28 mcooper
- X * Add copywrite notice.
- X *
- X * Revision 1.12 90/12/15 17:51:46 mcooper
- X * Add #ifdef HAS_VARARGS around include for <varargs>.
- X *
- X * Revision 1.11 90/11/13 16:39:28 mcooper
- X * Add #ifdef HAS_VARARGS for systems without
- X * varargs.
- X *
- X * Revision 1.10 90/11/13 15:28:01 mcooper
- X * - Add OptBool cvtarg routine.
- X * - Print default values in HelpOptions()
- X * when appropriate.
- X *
- X * Revision 1.9 90/11/13 15:19:00 mcooper
- X * Added supported for options being both
- X * SepArg and StickyArg.
- X *
- X * Revision 1.8 90/10/30 21:02:31 mcooper
- X * Need to exit() if -help is specified.
- X *
- X * Revision 1.7 90/10/30 20:24:33 mcooper
- X * Fixed bug in UsageString().
- X *
- X * Revision 1.6 90/10/30 19:53:05 mcooper
- X * Cleaned up some NeXT cc and lint stuff.
- X *
- X * Revision 1.5 90/10/30 19:45:31 mcooper
- X * Remove unneeded paramter to HelpOptions().
- X *
- X * Revision 1.4 90/10/29 14:47:42 mcooper
- X * Added real function UsageString() to
- X * handle formating usage option strings.
- X *
- X * Revision 1.3 90/10/29 14:17:00 mcooper
- X * Allow options to be abbreviated
- X * (for all non StickArg options).
- X *
- X * Revision 1.2 90/10/26 15:56:11 mcooper
- X * - Fix bug in SepArg code that ate arguments.
- X * - Cleanup help message.
- X * - Add ArgHidden code.
- X *
- X * Revision 1.1 90/10/26 14:42:51 mcooper
- X * Initial revision
- X *
- X */
- X
- X/*
- X * Functions to parse options.
- X */
- X
- X#include "options.h"
- X#ifdef HAS_VARARGS
- X#include <varargs.h>
- X#endif
- X
- Xchar *OptionChars = "-+"; /* Default option switching characters */
- Xchar *ProgramName = NULL; /* Name of this program */
- Xchar *UsageString();
- Xstatic int isopt();
- Xstatic int suppress_help_msg = 0;
- Xchar *strcat();
- X
- X/*
- X * ParseOptions - Parse options found in argv using "options".
- X * Returns the number of options parsed if there
- X * were no errors. Returns -1 if an error occurs.
- X */
- Xint ParseOptions(options, num_options, argc, argv)
- X OptionDescRec *options;
- X int num_options;
- X int argc;
- X char **argv;
- X{
- X OptionDescRec *opt;
- X register int x;
- X char *p;
- X
- X if (ProgramName == NULL)
- X ProgramName = argv[0];
- X
- X#ifdef OPTION_DEBUG
- X (void) printf("Option list is:\n");
- X for (x = 0; x < num_options; ++x) {
- X opt = &options[x];
- X (void) printf("%s\n", opt->option);
- X }
- X
- X (void) printf("Arguments (%d):", argc);
- X for (x = 0; x < argc; ++x) {
- X (void) printf(" %s", argv[x]);
- X }
- X (void) printf("\n");
- X#endif /* OPTION_DEBUG */
- X
- X for (x = 1; x < argc; ++x) {
- X if (strcmp(HELPSTR, argv[x]) == 0) {
- X HelpOptions(options, num_options, (char **)NULL);
- X exit(0);
- X }
- X
- X opt = FindOption(options, num_options, argv[x]);
- X if (opt == NULL) {
- X if (isopt(argv[x])) { /* this was suppose to be an option */
- X UsageOptions(options, num_options, argv[x]);
- X return(-1);
- X } else { /* must be end of options */
- X break;
- X }
- X }
- X
- X if (opt->flags & NoArg) {
- X if (!(*opt->cvtarg)(opt, opt->value, FALSE)) {
- X UsageOptions(options, num_options, opt->option);
- X return(-1);
- X }
- X } else if (opt->flags & IsArg) {
- X if (!(*opt->cvtarg)(opt, opt->option, FALSE)) {
- X UsageOptions(options, num_options, opt->option);
- X return(-1);
- X }
- X } else if ((opt->flags & StickyArg) && (opt->flags & SepArg)) {
- X p = (char *) &argv[x][strlen(opt->option)];
- X if (!*p) { /*** SepArg ***/
- X if (x + 1 >= argc || isopt(argv[x+1])) {
- X if (opt->value == (caddr_t) NULL) {
- X UserError("%s: Option requires an argument.", argv[x]);
- X UsageOptions(options, num_options, opt->option);
- X return(-1);
- X }
- X p = opt->value;
- X } else {
- X p = argv[++x];
- X }
- X }
- X if (!(*opt->cvtarg)(opt, p, TRUE)) {
- X UsageOptions(options, num_options, opt->option);
- X return(-1);
- X }
- X } else if (opt->flags & StickyArg) {
- X p = (char *) &argv[x][strlen(opt->option)];
- X if (!*p) {
- X if (opt->value == (caddr_t) NULL) {
- X UserError("%s: Option requires an argument.", argv[x]);
- X UsageOptions(options, num_options, opt->option);
- X return(-1);
- X } else {
- X p = opt->value;
- X }
- X }
- X if (!(*opt->cvtarg)(opt, p, TRUE)) {
- X UsageOptions(options, num_options, opt->option);
- X return(-1);
- X }
- X } else if (opt->flags & SepArg) {
- X if (x + 1 >= argc || isopt(argv[x+1])) {
- X if (opt->value == (caddr_t) NULL) {
- X UserError("%s: Option requires an argument.", argv[x]);
- X UsageOptions(options, num_options, opt->option);
- X return(-1);
- X } else {
- X p = opt->value;
- X }
- X } else {
- X p = argv[++x];
- X }
- X if (!(*opt->cvtarg)(opt, p, TRUE)) {
- X UsageOptions(options, num_options, opt->option);
- X return(-1);
- X }
- X } else if (opt->flags & SkipArg) {
- X x += 2;
- X } else if (opt->flags & SkipLine) {
- X return(x);
- X } else if (opt->flags & SkipNArgs) {
- X if (opt->value) {
- X x += atoi(opt->value);
- X } else {
- X UserError("Internal Error: No 'value' set for SkipNArgs.");
- X return(-1);
- X }
- X } else {
- X UserError("Internal Error: Unknown argument type for option '%s'.",
- X opt->option);
- X return(-1);
- X }
- X }
- X
- X return(x);
- X}
- X
- X/*
- X * FindOption - Find "option" in "options". Returns NULL if not found.
- X */
- XOptionDescRec *FindOption(options, num_options, option)
- X OptionDescRec *options;
- X int num_options;
- X char *option;
- X{
- X OptionDescRec *opt;
- X register int x;
- X
- X for (x = 0; x < num_options; ++x) {
- X opt = &options[x];
- X if (opt->flags & StickyArg) {
- X if (strncmp(option, opt->option, strlen(opt->option)) == 0)
- X return(opt);
- X } else {
- X if (strncmp(option, opt->option, strlen(option)) == 0)
- X return(opt);
- X }
- X }
- X
- X return(NULL);
- X}
- X
- X/*
- X * isopt - Is "str" an option string? Compare first char of str against
- X * list of option switch characters. Returns TRUE if it is an option.
- X */
- Xstatic int isopt(str)
- X char *str;
- X{
- X register char *p;
- X
- X for (p = OptionChars; p && *p; *++p) {
- X if (*str == *p) {
- X return(TRUE);
- X }
- X }
- X
- X return(FALSE);
- X}
- X
- X/*
- X * UsageOptions - Print a usage message based on "options".
- X */
- Xvoid UsageOptions(options, num_opts, badOption)
- X OptionDescRec *options;
- X int num_opts;
- X char *badOption;
- X{
- X OptionDescRec *opt;
- X char *optstr;
- X register int x;
- X int col, len;
- X
- X if (badOption)
- X (void) fprintf (stderr, "%s: bad command line option \"%s\"\r\n\n",
- X ProgramName, badOption);
- X
- X (void) fprintf (stderr, "usage: %s", ProgramName);
- X col = 8 + strlen(ProgramName);
- X for (x = 0; x < num_opts; x++) {
- X opt = &options[x];
- X if (opt->flags & ArgHidden)
- X continue;
- X optstr = UsageString(opt);
- X len = strlen(optstr) + 3; /* space [ string ] */
- X if (col + len > 79) {
- X (void) fprintf (stderr, "\r\n "); /* 3 spaces */
- X col = 3;
- X }
- X (void) fprintf (stderr, " [%s]", optstr);
- X col += len;
- X }
- X
- X if (suppress_help_msg)
- X (void) fprintf(stderr, "\r\n\n");
- X else
- X (void) fprintf(stderr,
- X "\r\n\nType \"%s %s\" for a full description.\r\n\n",
- X ProgramName, HELPSTR);
- X}
- X
- X/*
- X * HelpOptions - Print a nice help/usage message based on options.
- X */
- Xvoid HelpOptions(options, num_opts, message)
- X OptionDescRec *options;
- X int num_opts;
- X char **message;
- X{
- X OptionDescRec *opt;
- X register int x;
- X char **cpp;
- X
- X suppress_help_msg = 1;
- X UsageOptions(options, num_opts, (char *)NULL);
- X suppress_help_msg = 0;
- X
- X (void) fprintf (stderr, "where options include:\n");
- X for (x = 0; x < num_opts; x++) {
- X opt = &options[x];
- X if (opt->flags & ArgHidden)
- X continue;
- X (void) fprintf (stderr, " %-28s %s\n", UsageString(opt),
- X (opt->desc) ? opt->desc : "");
- X if (opt->value && opt->cvtarg != OptBool)
- X (void) fprintf (stderr, " %-28s [ Default value is %s ]\n",
- X "", opt->value);
- X }
- X
- X if (message) {
- X (void) putc ('\n', stderr);
- X for (cpp = message; *cpp; cpp++) {
- X (void) fputs (*cpp, stderr);
- X (void) putc ('\n', stderr);
- X }
- X (void) putc ('\n', stderr);
- X }
- X}
- X
- X/*
- X * UserError - Print a user error.
- X */
- X#ifdef HAS_VARARGS
- Xvoid UserError(va_alist)
- X va_dcl
- X{
- X va_list args;
- X char *fmt;
- X
- X va_start(args);
- X if (ProgramName)
- X (void) fprintf(stderr, "%s: ", ProgramName);
- X fmt = (char *) va_arg(args, char *);
- X (void) vfprintf(stderr, fmt, args);
- X va_end(args);
- X (void) fprintf(stderr, "\n");
- X}
- X#else
- Xvoid UserError(fmt, a1, a2, a3, a4, a5, a6)
- X char *fmt;
- X{
- X if (ProgramName)
- X (void) fprintf(stderr, "%s: ", ProgramName);
- X (void) fprintf(stderr, fmt, a1, a2, a3, a4, a5, a6);
- X (void) fprintf(stderr, "\n");
- X}
- X#endif
- X
- XOptBool(opt, value, docopy)
- X OptionDescRec *opt;
- X caddr_t value;
- X int docopy; /*ARGSUSED*/
- X{
- X char *vpp;
- X
- X *(int *) opt->valp = (int) strtol(value, &vpp, 0);
- X if (*vpp) {
- X UserError("Invalid integer argument for '%s'.", opt->option);
- X return(FALSE);
- X } else {
- X return(TRUE);
- X }
- X}
- X
- XOptInt(opt, value, docopy)
- X OptionDescRec *opt;
- X caddr_t value;
- X int docopy; /*ARGSUSED*/
- X{
- X char *vpp;
- X
- X *(int *) opt->valp = (int) strtol(value, &vpp, 0);
- X if (*vpp) {
- X UserError("Invalid integer argument for '%s'.", opt->option);
- X return(FALSE);
- X } else {
- X return(TRUE);
- X }
- X}
- X
- XOptShort(opt, value, docopy)
- X OptionDescRec *opt;
- X caddr_t value;
- X int docopy; /*ARGSUSED*/
- X{
- X char *vpp;
- X
- X *(short *) opt->valp = (short) strtol(value, &vpp, 0);
- X if (*vpp) {
- X UserError("Invalid integer argument for '%s'.", opt->option);
- X return(FALSE);
- X } else {
- X return(TRUE);
- X }
- X}
- X
- XOptLong(opt, value, docopy)
- X OptionDescRec *opt;
- X caddr_t value;
- X int docopy; /*ARGSUSED*/
- X{
- X char *vpp;
- X
- X *(long *) opt->valp = (long) strtol(value, &vpp, 0);
- X if (*vpp) {
- X UserError("Invalid integer argument for '%s'.", opt->option);
- X return(FALSE);
- X } else {
- X return(TRUE);
- X }
- X}
- X
- XOptStr(opt, value, docopy)
- X OptionDescRec *opt;
- X caddr_t value;
- X int docopy;
- X{
- X char *p;
- X
- X if (docopy) {
- X if ((p = (char *) malloc((unsigned)strlen(value)+1)) == NULL) {
- X UserError("Cannot malloc memory: %s", SYSERR);
- X return(FALSE);
- X }
- X (void) strcpy(p, value);
- X } else {
- X p = value;
- X }
- X
- X *(char **) opt->valp = p;
- X
- X return(TRUE);
- X}
- X
- Xstatic char *UsageString(opt)
- X OptionDescRec *opt;
- X{
- X static char buf[BUFSIZ], buf2[BUFSIZ];
- X
- X (void) sprintf(buf, opt->option);
- X (void) strcpy(buf2, "");
- X if (opt->usage) {
- X (void) sprintf(buf2, "%s%s%s%s",
- X ((opt->flags & StickyArg) &&
- X !((opt->flags & StickyArg) && (opt->flags & SepArg)))
- X ? "" : " ",
- X (opt->value) ? "[" : "",
- X opt->usage,
- X (opt->value) ? "]" : ""
- X );
- X }
- X (void) strcat(buf, buf2);
- X
- X return(buf);
- X}
- END_OF_FILE
- if test 10901 -ne `wc -c <'options.c'`; then
- echo shar: \"'options.c'\" unpacked with wrong size!
- fi
- # end of 'options.c'
- fi
- if test -f 'options.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'options.h'\"
- else
- echo shar: Extracting \"'options.h'\" \(2592 characters\)
- sed "s/^X//" >'options.h' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1990 Michael A. Cooper.
- X * This software may be freely distributed provided it is not sold for
- X * profit and the author is credited appropriately.
- X */
- X
- X/*
- X * $Header: /am/sol/src/common/usc/lib/libgen/RCS/options.h,v 1.7 90/12/15 18:13:30 mcooper Exp $
- X *
- X * $Log: options.h,v $
- X * Revision 1.7 90/12/15 18:13:30 mcooper
- X * Add copywrite notice.
- X *
- X * Revision 1.6 90/11/13 15:28:39 mcooper
- X * Add OptBool cvtarg routine.
- X *
- X * Revision 1.5 90/10/29 19:34:03 mcooper
- X * Fixed comment for NoArg.
- X *
- X * Revision 1.4 90/10/29 18:48:43 mcooper
- X * Cleanup some comments.
- X *
- X * Revision 1.3 90/10/29 14:47:29 mcooper
- X * UsageString is now a real function.
- X *
- X * Revision 1.2 90/10/26 15:55:44 mcooper
- X * Add defines for "__" and ArgHidden.
- X *
- X * Revision 1.1 90/10/26 14:42:53 mcooper
- X * Initial revision
- X *
- X */
- X
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/errno.h>
- X
- X#define Num_Opts(o) (sizeof(o)/sizeof(OptionDescRec))
- X#define HELPSTR "-help"
- X#define __ (caddr_t)
- X
- X#ifndef SYSERR
- X#define SYSERR sys_errlist[errno]
- X#endif
- X#ifndef TRUE
- X#define TRUE 1
- X#endif
- X#ifndef FALSE
- X#define FALSE 0
- X#endif
- X
- X/*
- X * Values for OptionDescRec.flags.
- X */
- X#define NoArg 0x001 /* No argument for this option. Use
- X OptionDescRec.value. */
- X#define IsArg 0x002 /* Value is the option string itself */
- X#define SepArg 0x004 /* Value is in next argument in argv */
- X#define StickyArg 0x008 /* Value is characters immediately following
- X option */
- X#define SkipArg 0x010 /* Ignore this option and the next argument in
- X argv */
- X#define SkipLine 0x020 /* Ignore this option and the rest of argv */
- X#define SkipNArgs 0x040 /* Ignore this option and the next
- X OptionDescRes.value arguments in argv */
- X#define ArgHidden 0x080 /* Don't show in usage or help messages */
- X
- X/*
- X * Option description record.
- X */
- Xtypedef struct {
- X char *option; /* Option string in argv */
- X int flags; /* Flag bits */
- X int (*cvtarg)(); /* Function to convert argument */
- X caddr_t valp; /* Variable to set */
- X caddr_t value; /* Default value to provide */
- X char *usage; /* Usage message */
- X char *desc; /* Description message */
- X} OptionDescRec, *OptionDescList;
- X
- Xvoid UsageOptions();
- Xvoid HelpOptions();
- Xvoid UserError();
- Xint ParseOptions();
- XOptionDescRec *FindOption();
- X
- Xint OptBool();
- Xint OptInt();
- Xint OptLong();
- Xint OptShort();
- Xint OptStr();
- X
- Xextern char *OptionChars;
- Xextern int errno;
- Xextern char *sys_errlist[];
- Xextern long strtol();
- Xextern char *malloc();
- Xextern char *strcpy();
- END_OF_FILE
- if test 2592 -ne `wc -c <'options.h'`; then
- echo shar: \"'options.h'\" unpacked with wrong size!
- fi
- # end of 'options.h'
- fi
- if test -f 'qterm.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'qterm.c'\"
- else
- echo shar: Extracting \"'qterm.c'\" \(24777 characters\)
- sed "s/^X//" >'qterm.c' <<'END_OF_FILE'
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /src/common/usc/bin/qterm/RCS/qterm.c,v 5.4 1991/03/21 02:09:40 mcooper Exp $";
- X#endif
- X
- X/*
- X * Copyright (c) 1990 Michael A. Cooper.
- X * This software may be freely distributed provided it is not sold for
- X * profit and the author is credited appropriately.
- X */
- X
- X/*
- X *------------------------------------------------------------------
- X *
- X * $Source: /src/common/usc/bin/qterm/RCS/qterm.c,v $
- X * $Revision: 5.4 $
- X * $Date: 1991/03/21 02:09:40 $
- X * $State: Exp $
- X * $Author: mcooper $
- X * $Locker: $
- X *
- X *------------------------------------------------------------------
- X *
- X * Michael A. Cooper
- X * Research and Development Group
- X * University Computing Services
- X * University of Southern California
- X * (mcooper@usc.edu)
- X *
- X *------------------------------------------------------------------
- X *
- X * $Log: qterm.c,v $
- X * Revision 5.4 1991/03/21 02:09:40 mcooper
- X * Fix memory buffer problem with some C
- X * compilers. (tp@vtold.vtol.fi)
- X *
- X * Revision 5.3 1991/03/16 05:36:30 mcooper
- X * Fix casting of (char) NULL problem.
- X *
- X * Revision 5.2 1991/03/12 00:46:24 mcooper
- X * Change CMASK to CHAR_CMASK to avoid conflict
- X * under AIX 3.1.
- X *
- X * Revision 5.1 1991/02/20 02:23:33 mcooper
- X * Cleanup #ifdef USG5 as part of port
- X * to UTS 2.1 (System V.3).
- X *
- X * Revision 5.0 1990/12/15 18:30:41 mcooper
- X * Version 5.
- X *
- X * Revision 4.13 90/12/15 18:14:23 mcooper
- X * Add copywrite.
- X *
- X * Revision 4.12 90/11/13 16:00:03 mcooper
- X * Convert OptInt's to OptBool's where needed.
- X *
- X * Revision 4.11 90/11/13 15:38:28 mcooper
- X * Make OLD_SepArg include both
- X * SepArg and StickyArg.
- X *
- X * Revision 4.10 90/11/08 15:41:08 mcooper
- X * Make sure qt_fullname is not 0 length.
- X *
- X * Revision 4.9 90/11/08 13:02:06 mcooper
- X * Fix bug that closes the tty when an error
- X * occurs during command line parsing.
- X *
- X * Revision 4.8 90/11/06 13:19:40 mcooper
- X * Changed command line options to new
- X * longer names.
- X *
- X * Revision 4.7 90/11/05 17:09:30 mcooper
- X * Update option help messages and option names
- X * to be more mnemonic.
- X *
- X * Revision 4.6 90/11/05 16:44:35 mcooper
- X * - Converted to use new ParseOptions() for
- X * command line parsing.
- X * - Major de-linting.
- X * - Convert dprintf() to use varargs (if
- X * HAS_VARARGS is defined).
- X * - Lots of misc. cleanup.
- X *
- X * Revision 4.5 89/10/20 22:50:49 mcooper
- X * Changed code indention to current local
- X * standard of 4. (This should also mess up
- X * everybody trying to do diff's from older versions!)
- X *
- X * Revision 4.4 89/10/20 14:03:48 mcooper
- X * Fixed command line parsing of "-f -q".
- X *
- X * Revision 4.3 88/06/16 19:43:46 mcooper
- X * - Added -T flag to wait until timeout when
- X * listening for response string. This solves
- X * problem when the first entry in a table
- X * doesn't have a response string with a
- X * common ending character to look for.
- X * - Added -I flag for "intense" query mode.
- X * - Cleaned up debugging a bit.
- X *
- X * Revision 4.2 88/06/08 15:30:53 mcooper
- X * Cleanup pass including removing
- X * extraneous debugging messages.
- X *
- X * Revision 4.1 88/04/25 13:24:38 mcooper
- X * Added -S option to print send and recieve
- X * strings as they are sent and recieved as
- X * suggested by David W. Sanderson
- X * (dws@attunix.att.com).
- X *
- X * Revision 4.0 88/03/08 19:30:59 mcooper
- X * Version 4.
- X *
- X * Revision 3.7 88/03/08 19:28:32 mcooper
- X * Major rewrite.
- X *
- X * Revision 3.6 88/03/08 15:31:35 mcooper
- X * General cleanup time.
- X *
- X * Revision 3.5 88/03/08 13:59:39 mcooper
- X * - Catch signals and fix terminal modes.
- X * - Don't allow alarm times of 0.
- X * - Support for HP-UX machines and cleaner
- X * listen() code from Zenon Fortuna,
- X * HP-UX Support, Hewlett-Packard Vienna.
- X *
- X * Revision 3.4 87/10/07 15:16:17 mcooper
- X * - Beautify code a bit.
- X * - Add -w <N> option to set the wait time.
- X *
- X * Revision 3.3 87/08/24 19:25:32 mcooper
- X * The following based on code from Frank Crawford
- X * <frank@teti.qhtours.OZ>:
- X * - Use $TERM as output string when the terminal
- X * type is not known instead of "dumb".
- X * - Regular Expressions are now supported. RE are
- X * started with a leading `\'.
- X * - Octal values may now be used in send/recieve strings.
- X *
- X * Revision 3.1 87/08/03 15:21:07 mcooper
- X * As pointed out by Scott H. Robinson <shr@cetus.ece.cmu.edu>,
- X * the -F switch does work. Problem was that it never read
- X * in the ~/.qterm file.
- X *
- X * Revision 3.0 87/06/30 19:07:59 mcooper
- X * Release of version 3.
- X *
- X * Revision 2.4 87/04/29 19:28:35 mcooper
- X * In readtabfile() we now do special
- X * things when opening "file" fails
- X * depending on the bequiet flag.
- X *
- X * Revision 2.3 87/04/29 13:11:37 mcooper
- X * - No more "internal" table. The master
- X * table is read from a file (TABFILE).
- X * This makes ~/.qterm stuff much cleaner.
- X * - Error handling for qtermtab files is
- X * much more informative now.
- X * - More things I can't remember.
- X *
- X * Revision 2.2 87/03/05 21:01:28 mcooper
- X * Fixed system V compiler problem.
- X *
- X * Revision 2.1 87/03/01 19:43:22 mcooper
- X * Be more intelligent about the size of
- X * the default terminal table.
- X *
- X * Revision 2.0 87/03/01 19:20:00 mcooper
- X * General cleanup.
- X *
- X *------------------------------------------------------------------
- X */
- X
- X
- X/*
- X * qterm - Query Terminal
- X *
- X * qterm is used to query a terminal to determine the name of the terminal.
- X * This is done by sending a fairly universal string "\33Z" to the terminal,
- X * reading in a response, and comparing it against a master table of responses
- X * and names. The "name" printed to standard output should be one found in
- X * the termcap(5) database.
- X *
- X * Putting a line in your ".login" file such as:
- X *
- X * setenv TERM `qterm`
- X *
- X * or the following lines in your ".profile" file:
- X *
- X * TERM=`qterm`
- X * export TERM
- X *
- X * will set your terminal type automagically.
- X *
- X * If you add a terminal to the master table, please also send me a copy
- X * so that I may put it into my version.
- X *
- X * Michael Cooper
- X * Internet: mcooper@usc.edu
- X * UUCP: ...!rutgers!usc!mcooper
- X * BITNET: mcooper@gamera
- X */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <pwd.h>
- X#include <signal.h>
- X#include <sys/ioctl.h>
- X#include <setjmp.h>
- X#ifdef USG5
- X# include <termio.h>
- X#else /*USG5*/
- X# include <sys/file.h>
- X# include <sgtty.h>
- X#endif /*USG5*/
- X#include "qterm.h"
- X#include "options.h"
- X#ifdef HAS_VARARGS
- X#include <varargs.h>
- X#endif /*HAS_VARARGS*/
- X
- X#ifdef USG5
- Xstruct termio _ntty, _otty;
- X#else
- Xstruct sgttyb _tty;
- X#endif
- Xint _tty_ch = 2;
- Xchar recvbuf[SIZE];
- Xchar *progname;
- Xchar *termfile = NULL;
- X
- Xint debug = FALSE; /* Debug mode */
- Xint use_alt_str = FALSE; /* Alternate string */
- Xint towait = FALSE; /* Time out wait flag */
- Xint always_send = FALSE; /* Intense query mode */
- Xint longname = FALSE; /* Print long terminal name */
- Xint sent_chars = FALSE; /* Print strings sent from the terminal */
- Xint watch_chars = FALSE; /* Watch strings as they are sent and recv. */
- Xint quiet = FALSE; /* Quiet mode */
- Xint do_usrtabfile = FALSE; /* Use user's own .qtermtab file */
- Xint do_systabfile = TRUE; /* Use the system's qterm tab file */
- Xint almwait = WAIT; /* Wait (timeout) interval */
- X
- X/*
- X * Old options should not be visable in help and usage messages.
- X */
- X#ifdef OPT_COMPAT
- X#define OLD_NoArg NoArg|ArgHidden
- X#define OLD_SepArg SepArg|StickyArg|ArgHidden
- X#define fFLAG "-f"
- X#define FFLAG "-F"
- X#endif
- X
- X/*
- X * Command line options table.
- X */
- XOptionDescRec opts[] = {
- X#ifdef OPT_COMPAT
- X {"-a", OLD_NoArg, OptInt, (caddr_t) &use_alt_str, "1",
- X (char *)NULL, "Use alternate query string"},
- X {"-s", OLD_NoArg, OptInt, (caddr_t) &sent_chars, "1",
- X (char *)NULL, "Display the characters the terminal sent"},
- X {"-t", ArgHidden|OLD_NoArg, OptInt, (caddr_t) &sent_chars, "1",
- X (char *)NULL, "Display the characters the terminal sent"},
- X {"-I", OLD_NoArg, OptInt, (caddr_t) &always_send, "1",
- X (char *)NULL, "Always send the terminal query string"},
- X {"-T", OLD_NoArg, OptInt, (caddr_t) &towait, "1",
- X (char *)NULL, "Enable time out wait"},
- X {"-S", OLD_NoArg, OptInt, (caddr_t) &watch_chars, "1",
- X (char *)NULL, "Print strings as they are sent and received"},
- X {"-q", OLD_NoArg, OptInt, (caddr_t) &quiet, "1",
- X (char *)NULL, "Enable quite mode"},
- X {"-f", OLD_SepArg, OptStr, (caddr_t) &termfile, fFLAG,
- X "<tabfile>", "Try <tabfile>, then ~/.qtermtab, then system tabfile"},
- X {"-F", OLD_SepArg, OptStr, (caddr_t) &termfile, FFLAG,
- X "<tabfile>", "Try <tabfile>, then ~/.qtermtab"},
- X {"-l", OLD_NoArg, OptInt, (caddr_t) &longname, "1",
- X (char *)NULL, "Output only the long (verbose) terminal name"},
- X {"-d", OLD_NoArg, OptInt, (caddr_t) &debug, "1",
- X (char *)NULL, "Enable debug mode"},
- X {"-w", OLD_SepArg, OptInt, (caddr_t) &almwait, __ NULL,
- X "<interval>", "Wait (timeout) period (in seconds)"},
- X#endif /*OPT_COMPAT*/
- X {"+alt", NoArg, OptBool, (caddr_t) &use_alt_str, "1",
- X (char *)NULL, "Use alternate query string"},
- X {"-alt", NoArg, OptBool, (caddr_t) &use_alt_str, "0",
- X (char *)NULL, "Don't use alternate query string"},
- X {"+always", NoArg, OptBool, (caddr_t) &always_send, "1",
- X (char *)NULL, "Always send the terminal query string"},
- X {"-always", NoArg, OptBool, (caddr_t) &always_send, "0",
- X (char *)NULL, "Don't always send the terminal query string"},
- X {"-file", SepArg, OptStr, (caddr_t) &termfile, __ NULL,
- X "<tabfile>", "Use <tabfile> to query terminal"},
- X {"+longname",NoArg, OptBool, (caddr_t) &longname, "1",
- X (char *)NULL, "Output only the long (verbose) terminal name"},
- X {"-longname",NoArg, OptBool, (caddr_t) &longname, "0",
- X (char *)NULL, "Don't output the long (verbose) terminal name"},
- X {"+quiet", NoArg, OptBool, (caddr_t) &quiet, "1",
- X (char *)NULL, "Enable quiet mode"},
- X {"-quiet", NoArg, OptBool, (caddr_t) &quiet, "0",
- X (char *)NULL, "Disable quiet mode"},
- X {"+sent", NoArg, OptBool, (caddr_t) &sent_chars, "1",
- X (char *)NULL, "Display the characters the terminal sent"},
- X {"-sent", NoArg, OptBool, (caddr_t) &sent_chars, "0",
- X (char *)NULL, "Don't display the characters the terminal sent"},
- X {"+timeout",NoArg, OptBool, (caddr_t) &towait, "1",
- X (char *)NULL, "Enable time out wait"},
- X {"-timeout",NoArg, OptBool, (caddr_t) &towait, "0",
- X (char *)NULL, "Disable time out wait"},
- X {"+usrtab", NoArg, OptBool, (caddr_t) &do_usrtabfile, "1",
- X (char *)NULL, "Enable using ~/.qtermtab"},
- X {"-usrtab", NoArg, OptBool, (caddr_t) &do_usrtabfile, "0",
- X (char *)NULL, "Disable using ~/.qtermtab"},
- X {"-wait", SepArg, OptInt, (caddr_t) &almwait, __ NULL,
- X "<interval>", "Wait (timeout) period (in seconds)"},
- X {"+watch", NoArg, OptBool, (caddr_t) &watch_chars, "1",
- X (char *)NULL, "Watch the characters sent and recieved"},
- X {"-watch", NoArg, OptBool, (caddr_t) &watch_chars, "0",
- X (char *)NULL, "Don't watch the characters sent and recieved"},
- X {"+systab", NoArg, OptBool, (caddr_t) &do_usrtabfile, "1",
- X (char *)NULL, "Enable using system qtermtab file"},
- X {"-systab", NoArg, OptBool, (caddr_t) &do_systabfile, "0",
- X (char *)NULL, "Disable using system qtermtab file"},
- X {"-debug", ArgHidden|NoArg, OptInt, (caddr_t) &debug, "1",
- X (char *)NULL, "Enable debug mode"},
- X};
- X
- XFILE *fopen();
- Xchar *decode();
- Xchar *getenv();
- Xchar *malloc();
- Xchar *re_comp();
- Xchar *strcat();
- Xchar *xmalloc();
- Xint alarm();
- Xint found = FALSE;
- Xint modes_set = FALSE;
- Xjmp_buf env;
- Xstruct termtable *compare();
- Xstruct passwd *getpwuid();
- Xvoid catch();
- Xvoid done();
- Xvoid dprintf();
- Xvoid exit();
- Xvoid myperror();
- Xvoid mktable();
- Xvoid notrecognized();
- Xvoid proctab();
- Xvoid wakeup();
- X#ifdef USG5
- Xchar *regcmp();
- X#endif /* USG5 */
- X
- Xmain(argc, argv)
- X int argc;
- X char **argv;
- X{
- X config(argc, argv);
- X setmodes();
- X mktable();
- X proctab((struct termtable *)NULL);
- X resetmodes();
- X
- X if (!found) {
- X notrecognized();
- X }
- X
- X exit(0);
- X}
- X
- X/*
- X * Config() - Perform configuration operations.
- X */
- Xconfig(argc, argv)
- X int argc;
- X char **argv;
- X{
- X progname = argv[0];
- X
- X /*
- X * Parse command line args
- X */
- X if (ParseOptions(opts, Num_Opts(opts), argc, argv) < 0) {
- X done(1);
- X /*NOTREACHED*/
- X }
- X
- X /*
- X * Check results of command line parsing and perform any
- X * needed post processing.
- X */
- X
- X if (longname)
- X quiet = TRUE;
- X
- X if (almwait == 0) {
- X (void) fprintf(stderr,
- X "%s: Alarm (wait) time must be greater than 0.\n",
- X progname);
- X done(1);
- X /*NOTREACHED*/
- X }
- X
- X#ifdef OPT_COMPAT
- X /*
- X * Kludgy stuff to be backwards compatable for command line options.
- X */
- X if (termfile) {
- X if (strcmp(termfile, fFLAG) == 0) {
- X do_usrtabfile = TRUE;
- X do_systabfile = TRUE;
- X termfile = NULL;
- X } else if (strcmp(termfile, FFLAG) == 0) {
- X do_usrtabfile = TRUE;
- X do_systabfile = FALSE;
- X termfile = NULL;
- X }
- X }
- X#endif /*OPT_COMPAT*/
- X
- X dprintf("[ %s debug mode enabled ]\n\n", progname);
- X}
- X
- X/*
- X * Set signal catches and terminal modes
- X */
- Xsetmodes()
- X{
- X if (!isatty(0)) {
- X (void) fprintf(stderr, "%s: Not a tty.\n", progname);
- X done(0);
- X /*NOTREACHED*/
- X }
- X
- X /*
- X * Set output buffers
- X */
- X setbuf(stdout, (char *)0);
- X if (debug)
- X setbuf(stderr, (char *)0);
- X
- X /*
- X * Cleanup terminal modes & such if we are killed
- X */
- X (void) signal(SIGINT, catch);
- X (void) signal(SIGHUP, catch);
- X (void) signal(SIGTERM, catch);
- X
- X /*
- X * Set terminal modes
- X */
- X#ifdef USG5
- X if (ioctl(_tty_ch, TCGETA, &_otty) < 0)
- X#else
- X if (ioctl(_tty_ch, TIOCGETP, &_tty) < 0)
- X#endif /* USG5 */
- X {
- X myperror("gtty");
- X done(1);
- X /*NOTREACHED*/
- X }
- X#ifdef USG5
- X _ntty = _otty;
- X#endif /* USG5 */
- X
- X if (crmode() < 0) {
- X myperror("crmode");
- X done(1);
- X /*NOTREACHED*/
- X }
- X
- X if (noecho() < 0) {
- X myperror("noecho");
- X done(1);
- X /*NOTREACHED*/
- X }
- X modes_set = TRUE;
- X}
- X
- X/*
- X * Reset terminal modes
- X */
- Xresetmodes()
- X{
- X if (modes_set) {
- X (void) nocrmode();
- X (void) echo();
- X }
- X}
- X
- X/*
- X * Print info about terminal structure t.
- X */
- Xprinfo(t, what)
- X struct termtable *t;
- X int what;
- X{
- X int len = 0;
- X int st = FALSE;
- X
- X if (t && t->qt_termname && (recvbuf[0] != (char) NULL)) {
- X if (debug || sent_chars) {
- X len = strlen(recvbuf);
- X (void) fprintf(stderr, "%s received %d character%s:",
- X progname, len, (len == 1) ? "" : "s");
- X (void) fprintf(stderr, " %s\n", decode(recvbuf));
- X }
- X
- X if (!quiet) {
- X (void) fprintf(stderr, "Terminal recognized as %s",
- X t->qt_termname);
- X if (t->qt_fullname && t->qt_fullname[0])
- X (void) fprintf(stderr, " (%s)\n", t->qt_fullname);
- X else
- X (void) fprintf(stderr, "\n");
- X }
- X
- X if (longname) {
- X if (t->qt_fullname && t->qt_fullname[0])
- X (void) printf("%s\n", t->qt_fullname);
- X else
- X (void) fprintf(stderr, "%s: No full terminal name for %s.\n",
- X progname, t->qt_termname);
- X } else {
- X (void) printf("%s\n", t->qt_termname);
- X }
- X
- X found = TRUE;
- X done(0);
- X /*NOTREACHED*/
- X } else {
- X found = FALSE;
- X
- X if (what) {
- X notrecognized();
- X done(1);
- X /*NOTREACHED*/
- X }
- X }
- X
- X return(st);
- X}
- X
- X/*
- X * compare - actually compare what we received against the table.
- X */
- Xstruct termtable *compare(str)
- X char *str;
- X{
- X#ifdef USG5
- X register char *reexp;
- X#endif /* USG5 */
- X register struct termtable *t;
- X char buf[BUFSIZ];
- X
- X dprintf("compare %s\n", (str && str[0]) ? decode(str) : "nothing");
- X (void) alarm((unsigned)0);
- X
- X if (strlen(str) == 0)
- X return(NULL);
- X
- X for (t = termtab; t != NULL; t = t->nxt) {
- X dprintf(" with %s ", decode(t->qt_recvstr));
- X (void) sprintf(buf, "^%s$", t->qt_recvstr);
- X
- X#ifdef USG5
- X if ((reexp = regcmp(buf, NULL)) == NULL) {
- X#else
- X if (re_comp((char *)buf) != NULL) {
- X#endif /* USG5 */
- X (void) fprintf(stderr, "%s: bad regular expression: \"%s\"\n",
- X progname, t->qt_recvstr);
- X done(1);
- X /*NOTREACHED*/
- X }
- X
- X#ifdef USG5
- X if (regex(reexp, str) != NULL) {
- X#else
- X if (re_exec(str) == 1) {
- X#endif /* USG5 */
- X found = TRUE;
- X dprintf("\tOK\n");
- X return(t);
- X }
- X
- X dprintf("\tNOPE\n");
- X#ifdef USG5
- X (void) free(reexp);
- X#endif /* USG5 */
- X }
- X found = FALSE;
- X
- X return(NULL);
- X}
- X
- X/*
- X * getch - read in a character at a time.
- X */
- Xgetch()
- X{
- X char c;
- X
- X (void) read(0, &c, 1);
- X
- X return(c & CHAR_MASK);
- X}
- X
- X/*
- X * decode - print str in a readable fashion
- X */
- Xchar *decode(str)
- X char *str;
- X{
- X register int len;
- X static char buf[BUFSIZ];
- X char tmp[10];
- X
- X if (!str)
- X return("(null)");
- X
- X (void) strcpy(buf, "");
- X while (*str) {
- X if (*str == ESC) {
- X (void) strcat(buf, "<esc> ");
- X } else if ((*str <= 33) || (*str >= 127)) {
- X (void) sprintf(tmp,"\\%#o ", (unsigned) *str);
- X (void) strcat(buf, tmp);
- X } else {
- X (void) sprintf(tmp,"%c ", *str);
- X (void) strcat(buf, tmp);
- X }
- X ++str;
- X }
- X
- X len = strlen(buf);
- X if (len && buf[len - 1] == ' ') {
- X buf[len - 1] = (char) NULL;
- X }
- X
- X return(buf);
- X}
- X
- X/*
- X * Make a termtab table
- X */
- Xvoid mktable()
- X{
- X char file[BUFSIZ];
- X struct passwd *pwd;
- X char *home;
- X
- X dprintf("[ initilizing term table... ]\n");
- X
- X if (termfile != NULL) {
- X (void) readtabfile(termfile, FALSE);
- X }
- X
- X if (do_usrtabfile) {
- X /*
- X * Try to read the user's own table
- X */
- X if ((home = getenv("HOME")) == NULL) {
- X if ((pwd = getpwuid(getuid())) == NULL) {
- X (void) fprintf(stderr,
- X "%s: Cannot find user info for uid %d.\n",
- X progname, getuid());
- X done(1);
- X /*NOTREACHED*/
- X }
- X home = pwd->pw_dir;
- X }
- X
- X (void) sprintf(file, "%s/%s", home, USRFILE);
- X if (readtabfile(file, TRUE) < 0) {
- X (void) sprintf(file, "%s/%s", home, OLDUSRFILE);
- X (void) readtabfile(file, TRUE);
- X }
- X }
- X
- X if (do_systabfile)
- X (void) readtabfile(TABFILE, FALSE);
- X
- X dprintf("[ mktable done ]\n");
- X}
- X
- Xint readtabfile(file, bequiet)
- X char *file;
- X int bequiet;
- X{
- X static int line = 0;
- X char lbuf[4][BUFSIZ];
- X char buf[BUFSIZ];
- X FILE *fd;
- X char *p, *fixctl();
- X char *errmsg = NULL;
- X struct termtable *t;
- X
- X if ((fd = fopen(file, "r")) == NULL) {
- X if (bequiet) {
- X dprintf("[ tab file '%s' can not read ]\n", file);
- X return(-1);
- X }
- X myperror(file);
- X done(1);
- X /*NOTREACHED*/
- X }
- X
- X dprintf("[ Read tab file '%s' ]\n", file);
- X
- X line = 0;
- X while (fgets(buf, sizeof(buf), fd)) {
- X ++line;
- X
- X if (buf[0] == '#' || buf[0] == '\n')
- X continue;
- X
- X lbuf[0][0] = lbuf[1][0] = lbuf[2][0] = lbuf[3][0] = (char) NULL;
- X
- X (void) sscanf(buf, "%s%s%s\t%[^\n]",
- X lbuf[0], lbuf[1], lbuf[2], lbuf[3]);
- X
- X if (lbuf[0][0] == (char) NULL)
- X continue;
- X
- X if (lbuf[1][0] == (char) NULL)
- X errmsg = "receive string";
- X
- X if (lbuf[2][0] == (char) NULL)
- X errmsg = "terminal name";
- X
- X if (errmsg) {
- X (void) fprintf(stderr, "%s: Line %d of %s: Error parsing %s.\n",
- X progname, line, file, errmsg);
- X done(1);
- X /*NOTREACHED*/
- X }
- X
- X t = (struct termtable *) xmalloc(sizeof(struct termtable));
- X
- X if (use_alt_str)
- X p = fixctl(ALTSEND, 0);
- X else
- X p = fixctl(lbuf[0], 0);
- X
- X t->qt_sendstr = (char *) xmalloc(strlen(p)+1);
- X (void) strcpy(t->qt_sendstr, p);
- X
- X p = fixctl(lbuf[1], 1);
- X t->qt_recvstr = (char *) xmalloc(strlen(p)+1);
- X (void) strcpy(t->qt_recvstr, p);
- X
- X t->qt_termname = (char *) xmalloc(strlen(lbuf[2])+1);
- X (void) strcpy(t->qt_termname, lbuf[2]);
- X
- X t->qt_fullname = (char *) xmalloc(strlen(lbuf[3])+1);
- X (void) strcpy(t->qt_fullname, lbuf[3]);
- X
- X dprintf("\n Send String = %s\n", decode(t->qt_sendstr));
- X dprintf("Expect String = %s\n", decode(t->qt_recvstr));
- X dprintf(" Terminal = '%s'\n", t->qt_termname);
- X dprintf(" Full Name = '%s'\n", t->qt_fullname);
- X
- X (void) addterm(t);
- X }
- X
- X return(0);
- X}
- X
- X/*
- X * Add termtab (n) entry to main termtab.
- X */
- Xint addterm(n)
- X struct termtable *n;
- X{
- X register struct termtable *t;
- X
- X if (!n)
- X return(-1);
- X
- X n->nxt = NULL;
- X
- X if (termtab == NULL) {
- X termtab = n;
- X } else {
- X t = termtab;
- X while(t && t->nxt)
- X t = t->nxt;
- X t->nxt = n;
- X }
- X
- X return(0);
- X}
- X
- X/*
- X * Listen for a response.
- X */
- Xvoid qterm_listen(q)
- X struct termtable *q;
- X{
- X static int i, len;
- X register char c;
- X char end;
- X
- X (void) alarm((unsigned)0);
- X (void) strcpy(recvbuf, "");
- X i = 0;
- X
- X len = strlen(q->qt_recvstr);
- X
- X if (len) {
- X end = q->qt_recvstr[len - 1];
- X } else {
- X end = 'c'; /* Fairly standard ANSI default */
- X }
- X
- X dprintf("\nlisten for %s\t [ len = %d, end = `%c' ]\n",
- X decode(q->qt_recvstr), len, end);
- X
- X /*
- X * If we don't get an initial character, bounce out
- X * of here and finish with done(0).
- X */
- X if (setjmp(env)) {
- X if (found) {
- X done(0);
- X /*NOTREACHED*/
- X }
- X (void) fflush(stdin);
- X proctab(q->nxt);
- X } else {
- X (void) signal(SIGALRM, wakeup);
- X (void) alarm((unsigned)almwait);
- X recvbuf[0] = getch();
- X (void) alarm((unsigned)0);
- X }
- X
- X /*
- X * Read in remaining response. Loop until ending character
- X * is received or until alarm goes off. If towait is set,
- X * then let alarm go off.
- X */
- X for (i = 1, c = -1; (!towait && (c != end)) || towait; ) {
- X if (setjmp(env)) {
- X recvbuf[i] = (char) NULL;
- X return;
- X } else {
- X (void) signal(SIGALRM, wakeup);
- X (void) alarm((unsigned)almwait);
- X c = getch();
- X (void) alarm((unsigned)0);
- X }
- X recvbuf[i++] = c;
- X }
- X recvbuf[i] = (char) NULL;
- X
- X dprintf("listen done. read %d chars.\n\n", i);
- X}
- X
- X/*
- X * Print a message since we didn't recognize this terminal.
- X */
- Xvoid notrecognized()
- X{
- X char *envterm;
- X
- X if ((envterm = getenv("TERM")) == NULL)
- X envterm = "dumb";
- X
- X if (!quiet)
- X (void) fprintf(stderr,
- X "Terminal NOT recognized - defaults to \"%s\".\n",
- X envterm);
- X
- X puts(envterm);
- X}
- X
- X/*
- X * Process entries in the termtable.
- X */
- Xvoid proctab(t)
- X struct termtable *t;
- X{
- X int st = FALSE;
- X static int firsttime = TRUE;
- X static struct termtable *lastt;
- X
- X dprintf("\n[ Processing entries ] \n");
- X
- X if (firsttime) {
- X t = termtab;
- X lastt = NULL;
- X }
- X
- X while ((!found || do_usrtabfile) && t && t->qt_sendstr && !st) {
- X /*
- X * If this is our first time or the sendstr is the same as
- X * last time, don't send it again.
- X */
- X if (always_send || firsttime || lastt == NULL ||
- X strcmp(t->qt_sendstr, lastt->qt_sendstr) != 0) {
- X
- X if (firsttime)
- X firsttime = FALSE;
- X
- X if (watch_chars)
- X (void) printf("Send: %s\n", decode(t->qt_sendstr));
- X
- X (void) fflush(stdin);
- X (void) fprintf(stderr, "%s", t->qt_sendstr);
- X (void) fflush(stderr);
- X
- X lastt = t;
- X (void) qterm_listen(t);
- X
- X if (watch_chars)
- X (void) printf("\tRead: %s\n", decode(recvbuf));
- X }
- X
- X st = prinfo(compare(recvbuf), FALSE);
- X
- X lastt = t;
- X t = t->nxt;
- X }
- X
- X if (!found)
- X notrecognized();
- X
- X done(0);
- X /*NOTREACHED*/
- X}
- X
- Xchar *fixctl(str, rex)
- X char *str;
- X int rex;
- X{
- X register int i;
- X static char buf[BUFSIZ];
- X
- X for (i = 0; str && *str; ) {
- X switch (*str) {
- X
- X case '\\':
- X if (isdigit(*++str)) {
- X buf[i] = 0;
- X while (isdigit(*str))
- X buf[i] = (char) (((int)buf[i] * 8) +
- X (int)*str++ - (int) '0');
- X i++;
- X } else
- X buf[i++] = *str++;
- X continue;
- X
- X case '^':
- X switch (*++str) {
- X case '?':
- X buf[i++] = '\177';
- X break;
- X default:
- X buf[i++] = *str & 037;
- X break;
- X }
- X break;
- X
- X /* Special R.E. symbols */
- X case '[':
- X case '*':
- X case '.':
- X case '$':
- X case '{':
- X case '(':
- X if (rex)
- X buf[i++] = '\\';
- X
- X default:
- X buf[i++] = *str;
- X }
- X *++str;
- X }
- X
- X buf[i] = (char) NULL;
- X
- X return(buf);
- X}
- X
- X/*
- X * xmalloc - Do a malloc with error checking.
- X */
- Xchar *xmalloc(size)
- X int size;
- X{
- X char *p;
- X
- X if ((p = malloc((unsigned) size)) == NULL) {
- X myperror("malloc");
- X done(1);
- X /*NOTREACHED*/
- X }
- X
- X return(p);
- X}
- X
- X#ifdef HAS_VARARGS
- Xvoid dprintf(va_alist)
- X va_dcl
- X{
- X va_list args;
- X char *fmt;
- X
- X if (!debug)
- X return;
- X
- X va_start(args);
- X fmt = (char *) va_arg(args, char *);
- X (void) vprintf(fmt, args);
- X va_end(args());
- X (void) fflush(stdout);
- X}
- X
- X#else /*HAS_VARARGS*/
- X
- Xvoid dprintf(fmt, a1, a2, a3, a4, a5, a6)
- X char *fmt;
- X{
- X if (!debug)
- X return;
- X
- X (void) printf(fmt, a1, a2, a3, a4, a5, a6);
- X (void) fflush(stdout);
- X}
- X#endif /*HAS_VARARGS*/
- X
- X/*
- X * Catch kill signals and cleanup.
- X */
- Xvoid catch()
- X{
- X done(2);
- X /*NOTREACHED*/
- X}
- X
- Xvoid wakeup()
- X{
- X dprintf("wakeup called\n");
- X longjmp(env, 1);
- X}
- X
- Xvoid myperror(msg)
- X char *msg;
- X{
- X (void) fprintf(stderr, "%s: ", progname);
- X perror(msg);
- X}
- X
- X/*
- X * Reset terminal and exit with status s.
- X */
- Xvoid done(s)
- X int s;
- X{
- X resetmodes();
- X exit(s);
- X}
- END_OF_FILE
- if test 24777 -ne `wc -c <'qterm.c'`; then
- echo shar: \"'qterm.c'\" unpacked with wrong size!
- fi
- # end of 'qterm.c'
- fi
- echo shar: End of archive 1 \(of 2\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 2 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked both archives.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-